package com.dxy.netty.tcppackagesolve;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.nio.charset.StandardCharsets;

/**
 * @Description 演示“tcp拆包-粘包问题”服务端处理器
 * <p>
 * 粘包与拆包原因
 * 1）粘包原因：
 * 发送的数据大小 小于 发送缓冲区，tcp就会把发送的数据多次写入缓冲区，此时发生粘包；
 * 接收数据方的应用层没有及时从 接收缓冲区读取数据，也会发生粘包；
 * <p>
 * 2）拆包原因：
 * 发送的数据大小 大于 tcp发送缓冲区，就会发生拆包；
 * 发送的数据大小 大于 报文最大长度，也会拆包；
 * <p>
 * 粘包拆包解决方法
 * 方法1）发送方为每一个数据包添加报文头部。头部至少包含数据包长度（类似http协议的头部length）。 通过这种方式，接收方通过读取头部的长度知道当前数据包的界限，并在界限处停止读取。
 * 方法2）发送方以固定长度封装数据包。如果不足，则补0填充。
 * 方法3）自定义设置数据包的界限标识，如添加特别标识（如======）。接收方通过标识可以识别不同的数据包；
 * @Author dangxianyue
 * @Date 2023/1/8 21:15
 */
public class TcpNettyServerHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private int count = 0;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        byte[] buffer = new byte[msg.readableBytes()];//声明一个数组
        msg.readBytes(buffer);//读取到buffer中
        String msgStr = new String(buffer, StandardCharsets.UTF_8);
        System.out.println("==========================");
        String countMsg = String.format("服务端已收到[%s]个数据包", ++this.count);
        System.out.println(countMsg + "，当前数据包：" + msgStr);

        //回送客户端
        ByteBuf responseBuf = Unpooled.copiedBuffer(countMsg, StandardCharsets.UTF_8);
        ctx.writeAndFlush(responseBuf);

    }
}
